package com.base.utils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;


public class ClassUtils {
	/**
	 * <p>将field名称转化为getFiled方法名</p>
	 * <br>
	 * 样例:<br>
	 * _toGetMethod("a")="getA";<br>
	 * @param p_field String field名称
	 * @return get{Filed}名称
	 * @see StringUtils.toUpperCaseFirstLetter(String p_str)
	 */
	private  static String _toGetMethod(String p_field) throws Exception{		
		if(StringUtils.isEmpty(p_field)) throw new UtilArgumentException();		
		return "get" + StringUtils.toUpperCaseFirstLetter(p_field);
	}
	
	/**
	 * <p>将field名称转化为setFiled方法名</p>
	 * <br>
	 * 样例:<br>
	 * _toSetMethod("a")="setA";<br>
	 * @param p_field  String field名称
	 * @return set{Filed}名称i
	 * @see com.olive.framework.utils.string.StringUtils.toUpperCaseFirstLetter(String p_str)
	 */
	private static String _toSetMethod(String p_field) throws Exception{
		if(StringUtils.isEmpty(p_field)) throw new UtilArgumentException();
		return "set" + StringUtils.toUpperCaseFirstLetter(p_field);
	}
	/**
	 * <p>获取对象的函数列表(Map("函数名称",函数对象));</p>
	 * <br>
	 * 样例:<br>
	 * public class Clazz {<br>
	 *	 	private String a;<br>
	 * 		private int b=1;<br>
	 * 		private Date c;<br>
	 * 		public static String fielldValue = "Yes";<br>
	 * 		public static String getStaticMethod(){<br>
	 * 			return "OK";<br>
	 * 		}<br>
	 * 		public String getA() {<br>
	 * 			return a;<br>
	 * 		}<br>
	 * 		public void setA(String a) {<br>
	 * 			this.a = a;<br>
	 * 		}<br>
	 * 		public int getB() {<br>
	 * 			return b;<br>
	 * 		}<br>
	 * 		public void setB(int b) {<br>
	 * 			this.b = b;<br>
	 * 		}<br>
	 * 		public Date getC() {<br>
	 * 			return c;<br>
	 * 		}<br>
	 * 		public void setC(Date c) {<br>
	 * 			this.c = c;<br>
	 *		};	<br>
	 * }<br>
	 * Map _map = ClassUtils.getMethods(Clazz.class);<br>
	 * _map.containsKey("getA")=true;<br>
	 * _map.containsKey("getB")=true;<br>
	 * _map.containsKey("getC")=true;<br>
	 * _map.containsKey("getK")=false;<br>; 
	 * @param p_cls Class 待反射类
	 * @return Map Map("函数名称",函数对象)
	 * @throws Exception
	 */
	public static Map getMethods(Class p_cls) throws Exception{
		if(null==p_cls)  throw new UtilArgumentException();		
		BeanInfo _beanInfo = Introspector.getBeanInfo(p_cls);		
		Map _mapMethods = new HashMap();
		MethodDescriptor[] methods = _beanInfo.getMethodDescriptors();
		for(int i=0;i<methods.length;i++){
			_mapMethods.put(methods[i].getName(), methods[i].getMethod());
		}
		return _mapMethods;		
	}
	/**
	 * <p>获取对象的函数列表(Map("函数名称",函数对象));</p>
	 * <br>
	 * 样例:<br>
	 * /**
	 * <p>获取对象的函数列表(Map("函数名称",函数对象));</p>
	 * <br>
	 * 样例:<br>
	 * public class Clazz {<br>
	 *	 	private String a;<br>
	 * 		private int b=1;<br>
	 * 		private Date c;<br>
	 * 		public static String fielldValue = "Yes";<br>
	 * 		public static String getStaticMethod(){<br>
	 * 			return "OK";<br>
	 * 		}<br>
	 * 		public String getA() {<br>
	 * 			return a;<br>
	 * 		}<br>
	 * 		public void setA(String a) {<br>
	 * 			this.a = a;<br>
	 * 		}<br>
	 * 		public int getB() {<br>
	 * 			return b;<br>
	 * 		}<br>
	 * 		public void setB(int b) {<br>
	 * 			this.b = b;<br>
	 * 		}<br>
	 * 		public Date getC() {<br>
	 * 			return c;<br>
	 * 		}<br>
	 * 		public void setC(Date c) {<br>
	 * 			this.c = c;<br>
	 *		};	<br>
	 * }<br>
	 * Clazz _clazz = new Clazz();
	 * Map _map = ClassUtils.getMethods(_clazz);
	 * _map.containsKey("getA")=true;<br>
	 * _map.containsKey("getB")=true;<br>
	 * _map.containsKey("getC")=true;<br>
	 * _map.containsKey("getK")=false;<br>; 
	 * @param p_obj Object 待反射对象
	 * @return Map Map("函数名称",函数对象)
	 * @throws Exception
	 * @see getMethods(Class p_cls)
	 */
	public static Map getMethods(Object p_obj) throws Exception{
		if(null==p_obj) throw new UtilArgumentException();		
		return getMethods(p_obj.getClass());
	}
	/**
	 * <p>根据名称获取方法对象</p>
	 * <br>
	 * 样例:<br>
	 * public class Clazz {<br>
	 *	 	private String a;<br>
	 * 		private int b=1;<br>
	 * 		private Date c;<br>
	 * 		public static String fielldValue = "Yes";<br>
	 * 		public static String getStaticMethod(){<br>
	 * 			return "OK";<br>
	 * 		}<br>
	 * 		public String getA() {<br>
	 * 			return a;<br>
	 * 		}<br>
	 * 		public void setA(String a) {<br>
	 * 			this.a = a;<br>
	 * 		}<br>
	 * 		public int getB() {<br>
	 * 			return b;<br>
	 * 		}<br>
	 * 		public void setB(int b) {<br>
	 * 			this.b = b;<br>
	 * 		}<br>
	 * 		public Date getC() {<br>
	 * 			return c;<br>
	 * 		}<br>
	 * 		public void setC(Date c) {<br>
	 * 			this.c = c;<br>
	 *		};	<br>
	 * }<br>
	 * Clazz _clazz  = new Clazz();
	 * Method _method = ClassUtils.getMethod(_clazz, "getA");
	 * _method.getName()="getA";
	 * _method = ClassUtils.getMethod(_clazz, "getK");
	 * _method = null;<br>
	 * @param p_obj Object 主体对象
	 * @param p_methodName String 方法名称
	 * @return Method 返回查找到的方法对象
	 * @throws Exception
	 */
	public static Method getMethod(Object p_obj,String p_methodName) throws Exception{
		if(null==p_obj || StringUtils.isEmpty(p_methodName)) throw new UtilArgumentException();
		Map _mtdMap = getMethods(p_obj);
		if(_mtdMap.containsKey(p_methodName)){
			return (Method)_mtdMap.get(p_methodName);
		}else{
			return null;
		}		
	}
	/**
	 * <p>判断对象是否含有指定方法</p>
	 * <br>
	 * 样例:<br>
	 * public class Clazz {<br>
	 *	 	private String a;<br>
	 * 		private int b=1;<br>
	 * 		private Date c;<br>
	 * 		public static String fielldValue = "Yes";<br>
	 * 		public static String getStaticMethod(){<br>
	 * 			return "OK";<br>
	 * 		}<br>
	 * 		public String getA() {<br>
	 * 			return a;<br>
	 * 		}<br>
	 * 		public void setA(String a) {<br>
	 * 			this.a = a;<br>
	 * 		}<br>
	 * 		public int getB() {<br>
	 * 			return b;<br>
	 * 		}<br>
	 * 		public void setB(int b) {<br>
	 * 			this.b = b;<br>
	 * 		}<br>
	 * 		public Date getC() {<br>
	 * 			return c;<br>
	 * 		}<br>
	 * 		public void setC(Date c) {<br>
	 * 			this.c = c;<br>
	 *		};	<br>
	 * }<br>
	 * Clazz _clazz  = new Clazz();<br>
	 * ClassUtils.containMethod(_clazz, "getA")=true;<br>
	 * ClassUtils.containMethod(_clazz, "getK")=false;<br>
	 * @param p_obj Object 待判断对象
	 * @param p_methodName String 包含方法名称
	 * @return boolean
	 * @throws Exception
	 * @see ClassUtils.getMethods(Object p_obj)
	 */
	public static boolean containMethod(Object p_obj,String p_methodName) throws Exception{
		if(null==p_obj || StringUtils.isEmpty(p_methodName)) throw new UtilArgumentException();
		Map _map = getMethods(p_obj);
		Iterator _it = _map.keySet().iterator();
		for(;_it.hasNext();){
			String _name = (String) _it.next();
			if(_name.equalsIgnoreCase(p_methodName)) return true;
		}
		return false;
	}
	
	/**
	 * <p>获取bean对象field信息</p>
	 * <br>
	 * 样例:<br>
	 * public class Clazz {<br>
	 *	 	private String a;<br>
	 * 		private int b=1;<br>
	 * 		private Date c;<br>
	 * 		public static String fielldValue = "Yes";<br>
	 * 		public static String getStaticMethod(){<br>
	 * 			return "OK";<br>
	 * 		}<br>
	 * 		public String getA() {<br>
	 * 			return a;<br>
	 * 		}<br>
	 * 		public void setA(String a) {<br>
	 * 			this.a = a;<br>
	 * 		}<br>
	 * 		public int getB() {<br>
	 * 			return b;<br>
	 * 		}<br>
	 * 		public void setB(int b) {<br>
	 * 			this.b = b;<br>
	 * 		}<br>
	 * 		public Date getC() {<br>
	 * 			return c;<br>
	 * 		}<br>
	 * 		public void setC(Date c) {<br>
	 * 			this.c = c;<br>
	 *		};	<br>
	 * }<br>
	 * Map _map = ClassUtils.getBeanFields(Clazz.class);<br>
	 * _map!=null;<br>
	 * _map.size()>0;<br>
	 * _map.containsKey("a")=true;<br>
	 * ((Field)_map.get("a")).getName()="a";<br>
	 * _map.containsKey("k")=false;<br>
	 * @param p_cls Class 待反射对象
	 * @return Map Map{属性名,属性对象}
	 * @throws Exception
	 */
	public static Map getBeanFields(Class p_cls) throws Exception{
		if(null==p_cls) throw new UtilArgumentException();
		Field[] _fields = p_cls.getDeclaredFields();
		Map _fMap = new HashMap();
		for(int i=0;i<_fields.length;i++){
			_fMap.put(_fields[i].getName(), _fields[i]);
		}
		return _fMap;
	}
	/**
	 * <p>获取bean对象field信息</p>
	 * <br>
	 * 样例:<br>
	 * public class Clazz {<br>
	 *	 	private String a;<br>
	 * 		private int b=1;<br>
	 * 		private Date c;<br>
	 * 		public static String fielldValue = "Yes";<br>
	 * 		public static String getStaticMethod(){<br>
	 * 			return "OK";<br>
	 * 		}<br>
	 * 		public String getA() {<br>
	 * 			return a;<br>
	 * 		}<br>
	 * 		public void setA(String a) {<br>
	 * 			this.a = a;<br>
	 * 		}<br>
	 * 		public int getB() {<br>
	 * 			return b;<br>
	 * 		}<br>
	 * 		public void setB(int b) {<br>
	 * 			this.b = b;<br>
	 * 		}<br>
	 * 		public Date getC() {<br>
	 * 			return c;<br>
	 * 		}<br>
	 * 		public void setC(Date c) {<br>
	 * 			this.c = c;<br>
	 *		};	<br>
	 * }<br>
	 * Clazz _clazz  = new Clazz();
	 * Map _map = ClassUtils.getBeanFields(_clazz);
	 * _map!=null;<br>
	 * _map.size()>0;<br>
	 * _map.containsKey("a")=true;<br>
	 * ((Field)_map.get("a")).getName()="a";<br>
	 * _map.containsKey("k")=false;<br>
	 * @param p_obj Object 待反射对象
	 * @return Map Map{属性名,属性对象}
	 * @throws Exception
	 * @see getBeanFields(Class p_cls)
	 */
	public static Map getBeanFields(Object p_obj) throws Exception{
		return getBeanFields(p_obj.getClass());
	} 
	
	/**
	 * <p>动态调用对象方法(Method)</p>
	 * <br>
	 * 样例:<br>
	 * public class Clazz {<br>
	 *	 	private String a;<br>
	 * 		private int b=1;<br>
	 * 		private Date c;<br>
	 * 		public static String fielldValue = "Yes";<br>
	 * 		public static String getStaticMethod(){<br>
	 * 			return "OK";<br>
	 * 		}<br>
	 * 		public String getA() {<br>
	 * 			return a;<br>
	 * 		}<br>
	 * 		public void setA(String a) {<br>
	 * 			this.a = a;<br>
	 * 		}<br>
	 * 		public int getB() {<br>
	 * 			return b;<br>
	 * 		}<br>
	 * 		public void setB(int b) {<br>
	 * 			this.b = b;<br>
	 * 		}<br>
	 * 		public Date getC() {<br>
	 * 			return c;<br>
	 * 		}<br>
	 * 		public void setC(Date c) {<br>
	 * 			this.c = c;<br>
	 *		};	<br>
	 * }<br>
	 * Clazz _clazz = new Clazz();
	 * Method _mtd = ClassUtils.getMethod(_clazz, "setA");
	 * ClassUtils.invokeMethod(_clazz, _mtd, new Object[]{"1"});
	 * _clazz.getA()="1";
	 * @param p_obj Object 对象
	 * @param p_mtd Method 方法
	 * @param p_args Object[] 方法参数
	 * @return Object 调用方法后的返回值
	 * @throws Exception
	 */
	public static Object invokeMethod(Object p_obj,Method p_mtd,Object[] p_args) throws Exception{
		if(null==p_obj || null==p_mtd) throw new UtilArgumentException();
		return p_mtd.invoke(p_obj,p_args);	
	}
	/**
	 * 调用对象方法
	 * @param p_obj Object 对象
	 * @param p_methodName String 方法名称
	 * @param p_args Object[] 调用函数传递的参数
	 * @return 调用函数返回值
	 * @throws Exception
	 * @see
	 *  getMethods(Object p_obj)<br>
	 * 	invokeMethod(Object p_obj,Method p_mtd,Object[] p_args)
	 */
	public static Object invokeMethod(Object p_obj,String p_methodName,Object[] p_args) throws Exception{
		if(null==p_obj || StringUtils.isEmpty(p_methodName)) throw new UtilArgumentException();
		Map _mapMtd = getMethods(p_obj);
		if(!_mapMtd.containsKey(p_methodName)){
			throw new Exception("ERROR:" + p_obj.getClass().toString() + "类不存在["+ p_methodName +"]方法" );
		}else{
			Method _method = (Method) _mapMtd.get(p_methodName);
			return invokeMethod(p_obj,_method,p_args);
		}
	}
	/**
	 * 动态调用类的静态方法
	 * @param p_cls Class 调用类
	 * @param p_mtd Method 方法
	 * @param p_args Object[] 方法参数
	 * @return 调用方法后的返回值
	 * @throws Exception
	 */
	public static Object invokeStaticMethod(Class p_cls,Method p_mtd,Object[] p_args) throws Exception{
		if(null==p_cls || null==p_mtd) throw new UtilArgumentException();
		return p_mtd.invoke(p_cls, p_args);
	}
	
	/**
	 * 调用Class的静态方法
	 * @param p_cls Class 具体类
	 * @param p_methodName String 静态方法名
	 * @param p_args Object[] 方法参数
	 * @return Object 调用静态方法后的返回值
	 * @throws Exception
	 */
	public static Object invokeStaticMethod(Class p_cls,String p_methodName,Object[] p_args) throws Exception{
		if(null==p_cls || StringUtils.isEmpty(p_methodName)) throw new UtilArgumentException();
		Map _mapMtd = getMethods(p_cls);
		if(!_mapMtd.containsKey(p_methodName)){
			throw new Exception("ERROR:" + p_cls.getClass().toString() + "类不存在["+ p_methodName +"]方法" );
		}else{
			Method _method = (Method) _mapMtd.get(p_methodName);
			return invokeMethod(p_cls,_method,p_args);
		}
	}
	
	/**
	 * 调用javabean对象的属性数值;
	 * @param p_obj Object 对象
	 * @param p_fieldName String 属性名称
	 * @return Object 属性值
	 * @throws Exception
	 */
	public static Object getBeanFieldValue(Object p_obj,String p_fieldName) throws Exception{
		if(null==p_obj || StringUtils.isEmpty(p_fieldName)) throw new UtilArgumentException();
		String _mtdName = _toGetMethod(p_fieldName);
		if(getBeanFields(p_obj).containsKey(p_fieldName)){			
			if(containMethod(p_obj,_mtdName)){
				return invokeMethod(p_obj,_mtdName,null);
			}else{
				throw new Exception("ERROR:" + p_obj.getClass().toString() + "类不存在["+ _mtdName +"]方法" );
			}
		}else{
			throw new Exception("ERROR:" + p_obj.getClass().toString() + "类不存在["+ p_fieldName +"]属性" );
		}
	}
	/**
	 * 获取对象的属性值
	 * @param p_obj	Object 对象
	 * @param p_field String 属性
	 * @return Object 对象的属性值
	 * @throws Exception
	 */
	public static Object getFieldValue(Object p_obj,String p_field) throws Exception{
		if(null==p_obj || StringUtils.isEmpty(p_field)) throw new UtilArgumentException();
		Field _field = p_obj.getClass().getDeclaredField(p_field);
		_field.setAccessible(true);
		return _field.get(p_obj);
	}
	/**
	 * 设置对象的属性值
	 * @param p_obj Object 对象
	 * @param p_fieldName String 属性名称
	 * @param p_fieldValue Object 属性值
	 * @throws Exception
	 */
	public static void setFieldValue(Object p_obj,String p_fieldName,Object p_fieldValue) throws Exception{
		if(null==p_obj || StringUtils.isEmpty(p_fieldName)) throw new UtilArgumentException();
		Field _field = p_obj.getClass().getDeclaredField(p_fieldName);		
		_field.setAccessible(true);
		_field.set(p_obj,p_fieldValue);
	}
	/**
	 * 获取class静态属性值
	 * @param p_cls Class 类
	 * @param p_fieldName String 静态属性
	 * @return 静态属性值
	 * @throws Exception
	 */
	public static Object getStaticFieldValue(Class p_cls,String p_fieldName) throws Exception{
		if(null==p_cls || StringUtils.isEmpty(p_fieldName)) throw new UtilArgumentException();
		Field _field = p_cls.getField(p_fieldName);
		return _field.get(p_cls);
	}
	/**
	 * 设置class静态属性值
	 * @param p_cls Class 类
	 * @param p_fieldName String 静态属性
	 * @param p_fieldValue Object 属性值
	 * @throws Exception
	 */
	public static void setStaticFieldValue(Class p_cls,String p_fieldName,Object p_fieldValue) throws Exception{
		if(null==p_cls || StringUtils.isEmpty(p_fieldName)) throw new UtilArgumentException();
		Field _field = p_cls.getDeclaredField(p_fieldName);		
//		_field.setAccessible(true);
		_field.set(p_cls,p_fieldValue);
	}
	/**
	 * 获取对象属性值（含内嵌对象，属性间以‘.’分割）
	 * @param p_obj Object 对象
	 * @param p_field String 属性名
	 * @return Object 返回值
	 * @throws Exception
	 * @see com.olive.framework.util.string.StringUtils#split(String p_str, String p_delim) <br>
	 * @see #invokeMethod(Object p_obj,String p_methodName,Object[] p_args)<br>
	 * @see #_toGetMethod(String p_field)
	 */
	public static Object getValue(Object p_obj,String p_field) throws Exception{
		if(null==p_obj || StringUtils.isEmpty(p_field)) throw new UtilArgumentException();
		String[] _fields = StringUtils.split(p_field, ".");
		Object _obj = p_obj;
		for(int i=0;i<_fields.length;i++){
			String _mtdName = _toGetMethod(_fields[i]);
			_obj = invokeMethod(_obj,_mtdName,null);
		}		
		return _obj;
	}
	
	/**
	 * 将指定的属性值进行拷贝，由p_src拷贝到p_target中
	 * @param p_src Object 源对象
	 * @param p_target Object 目标对象
	 * @param p_fields String[] 待拷贝属性列表
	 * @throws Exception
	 * @see
	 * getFieldValue(Object p_obj,String p_field)<br>
	 * setFieldValue(Object p_obj,String p_fieldName,Object p_fieldValue)
	 */
	public static void copy(Object p_src,Object p_target,String[] p_fields) throws Exception{
		if(null==p_src || null==p_target) throw new UtilArgumentException();
		if(null==p_fields) return;
		for(int i=0;i<p_fields.length;i++){
			try {
				Object _value = getFieldValue(p_src,p_fields[i]);
				setFieldValue(p_target,p_fields[i],_value);
			} catch (Exception e) {
				System.out.println("ERROR:copy属性[" + p_fields[i] + "]过程中,出现错误!");
				e.printStackTrace();
			}
		}
	}
	public static void copyBut(Object p_src,Object p_target,String[] p_fields) throws Exception{
		if(null==p_src || null==p_target) throw new UtilArgumentException();		
		Map _map = ClassUtils.getBeanFields(p_src);
		Map _mapFiled = new HashMap();
		if(null!=p_fields){
			for(int i=0;i<p_fields.length;i++){
				_mapFiled.put(p_fields[i], p_fields[i]);
			}
		}
		for(Iterator _it=_map.entrySet().iterator();_it.hasNext();){
			Map.Entry _entry = (Map.Entry)_it.next();
			if(!_mapFiled.containsKey(_entry.getKey())){
				String _field = (String)_entry.getKey();
				Object _value = getFieldValue(p_src,_field);
				setFieldValue(p_target,_field,_value);
			}
		}
	}
	/**
	 * 动态构建javabean对象
	 * @param p_cls Class 待构建javabean对象class
	 * @param p_map 属性值Map
	 * @return 动态构建的jo
	 * @throws Exception
	 * @see
	 *  invokeMethod(Object p_obj,String p_methodName,Object[] p_args)<br>
	 *  toSetMethod(String p_field)
	 */
	public static Object buildBean(Class p_cls,Map p_map) throws Exception{
		if(null==p_cls) throw new UtilArgumentException();
		Object _obj = p_cls.newInstance();
		if(null!=p_map){
			for(Iterator _it = p_map.entrySet().iterator();_it.hasNext();){
				Map.Entry _entry 	= (Entry) _it.next();
				String  _key 		= (String) _entry.getKey();
				Object _value 		= _entry.getValue();
				invokeMethod(_obj,_toSetMethod(_key),new Object[]{_value});
			}
		}
		return _obj;
	}
	/**
	 * 动态创建javabean对象
	 * @param p_src Object 数据源对象
	 * @param p_cls Class 待构建javabean对象class
	 * @param p_fields String[] 数据源对象属性列表
	 * @return Object 构建完成的javabean对象
	 * @throws Exception
	 * @see
	 * copy(Object p_src,Object p_target,String[] p_fields)
	 */
	public static Object buildBean(Object p_src,Class p_cls,String[] p_fields) throws Exception{
		if(null==p_src || null==p_cls) throw new UtilArgumentException();
		Object _obj = p_cls.newInstance();
		copy(p_src,_obj,p_fields);
		return _obj;
	}
	public static void main(String[] args)throws Exception {
		/*
		String[] _s = new String[]{"a","b"};
		Clazz _c1 = new Clazz();
		Clazz _c2 = new Clazz();
		_c1.setA("111");
		_c1.setB(222);
//		_c1.setC("333");
		
		ClassUtils.copy(_c1, _c2, _s);
		System.out.print("===="+_c2.getA()+","+_c2.getB()+","+_c2.getC());
		//////////////////////////////////
//		ClassUtils.setFieldValue(_c,"b",Integer.valueOf("666"));
		///////////////////////////////////////
//		Map m = new HashMap();
//		m.put("a", "11");
//		m.put("b", Integer.valueOf(22));
//		
//		Clazz c = (Clazz)ClassUtils.buildBean(Clazz.class,m);
//		System.out.print("===="+c.getA()+c.getB());
  */

	}
	
}
